package com.YHVision.qiuzhike.service.impl;

import com.YHVision.qiuzhike.exception.BusinessException;
import com.YHVision.qiuzhike.model.entity.Question;
import com.YHVision.qiuzhike.service.QuestionService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.YHVision.qiuzhike.common.ErrorCode;
import com.YHVision.qiuzhike.mapper.QuestionFavourMapper;
import com.YHVision.qiuzhike.model.entity.QuestionFavour;
import com.YHVision.qiuzhike.model.entity.User;
import com.YHVision.qiuzhike.service.QuestionFavourService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;


/**
 * 题目收藏服务实现
 *
 * @author <a href="">YHVision-小y</a>
 * @from <a href="todo">爱编程学习圈</a>
 */
@Service
@Slf4j
public class QuestionFavourServiceImpl extends ServiceImpl<QuestionFavourMapper, QuestionFavour> implements QuestionFavourService {


    @Resource
    private QuestionService questionService;
    /**
     * 题目收藏
     *
     * @param questionId
     * @param logingUser
     * @return
     */
    @Override
    public int doQuestionFavour(long questionId, User logingUser) {
        //获取questionId
        Question question = questionService.getById(questionId);
        //数据校验
        if (question == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        //根据用户的id查询对应的收藏,每个用户收藏是串行的
        //获取用户id
        Long userId = logingUser.getId();
        //使用事务代理和同步锁机制，并且锁要包裹住事务，保证数据一致性，避免事务代理失败
        // todo 代码优化
        QuestionFavourService questionFavourService =(QuestionFavourService) AopContext.currentProxy();
        //串行收藏
        synchronized (String.valueOf(userId).intern()){
            return questionFavourService.doQuestionFavourInner(userId,questionId);
        }
        
        
    }

    /**
     *
     * 可优化
     * todo 目前没有处理并发场景下的收藏数更新问题，比如多个用户同时收藏或取消收藏。可以通过乐观锁或数据库约束来防止数据不一致。
     * 封装事务方法
     * 题目收藏（内部服务）
     *
     * @param userId
     * @param questionId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int doQuestionFavourInner(long userId, long questionId) {
        //参数校验
        if (userId <= 0 || questionId <= 0){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"用户id或题目id无效");
        }
        QuestionFavour questionFavour = new QuestionFavour();
        questionFavour.setUserId(userId);
        questionFavour.setQuestionId(questionId);
        QueryWrapper<QuestionFavour> questionFavourQueryWrapper = new QueryWrapper<>(questionFavour);
        QuestionFavour oldQuestionFavour = this.getOne(questionFavourQueryWrapper);
        boolean result;
        //该题目用户已收藏
        if (oldQuestionFavour != null){
            result = this.remove(questionFavourQueryWrapper);
            if (result){
                //收藏问题数-1
                 result = questionService.update()
                         .eq("id",questionId)
                         .gt("favourNum",0)
                         .setSql("favourNum = favourNum - 1")
                         .update();
                 return result ? 1 : 0;
            }
            else {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
        }
        //该题用户未收藏
        else {
            result = this.save(questionFavour);
            if (result){
                //收藏数+1
                result = questionService.update()
                        .eq("id",questionId)
                        .setSql("favourNum = favourNum + 1")
                        .update();
                return result ? 1 : 0;
            }
            else {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 分页获取题目收藏列表
     *
     * @param page
     * @param queryWrapper
     * @return
     */
    @Override
    public Page<Question> listQuestionFavourByPage(IPage<Question> page, Wrapper<Question> queryWrapper,long favourUserId) {
        //参数校验
        if (favourUserId <= 0){
            return  new Page<>();
        }
        return baseMapper.listFavourQuestionByPage(page,queryWrapper,favourUserId);
    }
}
